
import java.io.IOException;
import java.util.ArrayList;

public class Pere extends Thread {

    private Process process;
    //private Tampon tamponDEmission;
    private ArrayList<Tampon> tableauTamponEmission;
    private Tampon tamponDeTrace;
    private Tampon tamponDeReception;
    private HorlogeLamport horloge;
    private boolean testTirage = false;
    private int numTirage;

    public Pere(Process _process) {
        this.process = _process;
        //this.tamponDEmission = this.process.getTamponDEmission();
        tableauTamponEmission=this.process.getTableauTamponEmetteur();
        this.tamponDeTrace = this.process.getTamponDeTrace();
        this.tamponDeReception = this.process.getTamponDeReception();
        this.horloge = this.process.getHorloge();
    }

   @Override
    public void run() {
        MessageUtile message = null;
        boolean test = true;
      
        while (test) 
        {
            System.out.println(process.getIdProcess() + " : Pere      : Attente d'un message ---------------------------> " + horloge.getCompteur());
            //message = receptionMessage();
            // On réceptionne dans un premier temps tous les messages
            while(this.process.getTamponDeReception().getTampon().size()!=0)
            {
                // Dans la fonction nous affichons le message dans la console et nous l'envoyons à la trace
                receptionMessage();
            }

            if (message.getContenu().equals("Fin")) 
            {
                System.out.println("Fermeture du thread p�re du processus " + process.getIdProcess());
                MessageUtile messageFin = new MessageUtile("Fin", 0, 0);
                // Dffuse à tous les process le message de fin. La fonction diffuse est codée dans le jalon suivant
                diffuseMessage(messageFin);
                test = false;
            } 
            else 
            {
                //On tire le numéro aléatoire
                int numAleatoire;
                numAleatoire = (int) (Math.random() * 30);

                //Si le nombre est compris entre 0 et 8, le process fait une action locale
                if (numAleatoire >= 0 && numAleatoire < 9 ) 
                {
                    //Action locale
                } 
                // Sinon si c'est compris entre 9 et 17 il envoit un message
                else if(numAleatoire >= 9 && numAleatoire < 18 )
                {
                    // On doit connaitre le nombre de process possible à qui le process
                    // actuel peut envoyer un message
                    // On retire un pour enlever du nombre total le process actuel
                    int nbProcess = this.process.getTableauProcess().size()-1;
                    
                    // On tire donc un nombre au hasard compris entre 1 et nbProcess
                    // Pour savoir a qui le message sera envoyé
                    
                    int random = (int)(Math.random() * (nbProcess-1)) + 1;
                    
                    // Création d'un message
                    MessageUtile messageEnvoyer = new MessageUtile();
                    horloge.incrementeHorloge();
                    //Envoi du message
                    envoiMessage(messageEnvoyer, random); 
                }
                // Sinon si c'est compris entre 18 et 27, il il diffuse un message
                else if(numAleatoire >= 18 && numAleatoire < 28 )
                {
                    // Diffusion d'un message
                    MessageUtile messageDiffusion = new MessageUtile("Diff",horloge.getCompteur(), this.process.getIdProcess());
                    horloge.incrementeHorloge();
                    diffuseMessage(messageDiffusion);
                }
                //Sinon il ferme en envoyant un message de fin
                else
                {
                    System.out.println(process.getIdProcess() + " : Pere      : Fermeture du SVG -------------------------------> " + horloge.getCompteur());
                    MessageUtile messageFin = new MessageUtile("Fin", 0, 0);
                    diffuseMessage(messageFin);
      		}
            }
           
        }
    }

    public void envoiMessage(Message message, int idProcessDestinataire) {
        
        int indiceTabThreadEmetteur=0;
        for (int i=0;i<this.process.getTableauEmetteur().size();i++)
        {
            if (this.process.getTableauEmetteur().get(i).getIdProcessDistant()==idProcessDestinataire)
            {
                indiceTabThreadEmetteur=i;
                i=this.process.getTableauEmetteur().size();
            }
        }
        tableauTamponEmission.get(indiceTabThreadEmetteur).setElementTampon(message);
        System.out.println(process.getIdProcess() + " : Pere      : Envoi d'un message -----------------------------> " + horloge.getCompteur());
    }

    // Fonction pour diffuser un message à tous les process interconnectés
    public void diffuseMessage(Message message)
    {
        // On parcourt le tableau de tous les emetteurs et on met le message dans chaque tampons
        for (int i=0;i<this.process.getTableauEmetteur().size();i++)
        {
             tableauTamponEmission.get(i).setElementTampon(message);
            System.out.println(process.getIdProcess() + " : Pere      : Envoi d'un message -----------------------------> " + horloge.getCompteur());
        }        
    }
    
    public MessageUtile receptionMessage() 
    {
        MessageUtile message = (MessageUtile) tamponDeReception.getElementTampon();
        horloge.incrementeHorloge(message.getEstampille());
        envoiTrace(message);
        System.out.println(process.getIdProcess() + " : Pere      : Reception d'un message -------------------------> " + horloge.getCompteur());
        //Affichage du message dans la console
        System.out.println(this.process.getIdProcess()+" Recoit le message : Contenu du message" + message.getContenu()+" Id du process depart : "+message.getIdProcess()+" Estampille :"+message.getEstampille());
        return message;
    }

    public void envoiTrace(MessageUtile message) {
        System.out.println(process.getIdProcess() + " : Pere      : Tracer --> " + message);
        Message ordre = new MessageOrdre(message.getContenu(), message.getIdProcess(), this.process.getIdProcess(), message.getEstampille(), this.horloge.getCompteur());
        tamponDeTrace.setElementTampon(ordre);
        System.out.println(process.getIdProcess() + " : Pere      : Envoi de --> " + ordre);
    }

    public void changeTestTirage() {
        this.testTirage = true;
    }

    public void setNumTirage(int num) {
        this.numTirage = num;
    }
}
